/*
 * @Author       : Zhao Lvhua zhaolh@linkcharging.com
 * @Date         : 2024-09-02 01:04:00
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 13:02:51
 * @FilePath     : \openchaoji-corelib\shared\src\OpenChaoJi_utility_transport_gbt27930_b_send.c
 * @Description  :
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include "OpenChaoJi_utility_transport_gbt27930_b.h"
#include "OpenChaoJi_utility_transport_gbt27930_b_private.h"

#if (OPENCHAOJI_CONFIG_ENABLE_GBT27930_B == CONFIG_YES)

extern bool s_transport_debug_enable;

/*
* @brief: gbt27930 B类系统不需要确认的消息发送函数
* @param {OpenChaoJi_context_utility_transport} *context 系统上下文指针，包含必要的环境信息。
* @param {can_data *} send_data 待发送数据
* @return: 成功返回0，失败返回-1。
*/
int16_t OpenChaoJi_transport_gbt27930_b_urm_send(struct OpenChaoJi_gbt27930_b_urmcb  * urmcb, const struct can_data * send_data)
{
    struct can_pdu pdu;
	uint8_t i;
	int16_t ret;

	if (send_data->len > 8)
	{
		//大于8字节的长消息不存在，error
		LOG_ERR("transportsend um send data length > 8 is error");
		return -1;
	}

	pdu.can_id.bit.sa = urmcb->src_addr;
	pdu.can_id.bit.ps = urmcb->dest_addr;
	pdu.can_id.bit.pf = PF_URSMIF;
	pdu.can_id.bit.dp = 0;
	pdu.can_id.bit.edp = 0;
	pdu.can_id.bit.p = 0x06;
	pdu.can_id.bit.rsvd = 0;
	pdu.can_dlc = 8;

	//填充数据，小于8字节的剩余数据域填0xff
	for (i = 0;i < 8;i++)
	{
		if (i < send_data->len){
			pdu.data[i] = send_data->data[i];
		}
		else{
			pdu.data[i] = 0xff;
		}
	}

    // 例如短包直接发送
    ret = (*urmcb->can_output_func)(urmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->b_ursm[%08X][%d]", urmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}

/*
* @brief: gbt27930 B类系统需要确认的短消息发送接口函数，该函数内部根据发送字节数区分长消息或短消息，进行缓存，然后执行发送
* @param {OpenChaoJi_context_utility_transport} *context系统上下文指针，包含必要的环境信息。
* @param {can_data *} send_data 待发送数据
* @return {*}成功返回0，失败返回-1。
*/
int16_t OpenChaoJi_transport_gbt27930_b_rm_write(struct OpenChaoJi_gbt27930_b_rmcb * rmcb, const struct can_data * send_data)
{
	struct OpenChaoJi_gbt27930_b_rmcb *Mscb = rmcb;

	if (send_data->len <= 8)
	{
		if (Mscb->sm_send_state == RSM_S1_SEND_ING)
		{
			//目前处于发送中，无法再次发送新的消息，go to error
			LOG_ERR("transportsend short message, current is sending, dont't send new message");
			return -1;
		}

		memcpy(Mscb->sm_send_buf,send_data->data,send_data->len);
		Mscb->sm_send_data_len = send_data->len;

		gbt27930_b_rsm_sent_data(rmcb);

		Mscb->sm_send_first_tick = OpenChaoJi_os_get_ticks();
		Mscb->sm_send_last_tick = OpenChaoJi_os_get_ticks();
		Mscb->sm_send_state = RSM_S1_SEND_ING;
		Mscb->sm_send_result = OPENCHAOJI_UTILITY_TRANSPORT_MSG_SEND_ING;

	}
	//长短消息处理
	else
	{
		if (Mscb->lm_send_state != LM_SEND_IDLE)
		{
			//目前处于发送中，无法再次发送新的消息，go to error
			LOG_ERR("transportsend long message, current is't idle, dont't send new message");
			return -1;
		}

		OPEN_CHAOJI_MEM_FREE_CHECK(Mscb->lm_send_buf);
		Mscb->lm_send_buf = OpenChaoJi_os_malloc(send_data->len);
		if (Mscb->lm_send_buf == NULL)
		{
			//内存申请失败 go to error
			LOG_CRIT("transportsend malloc null");
			return -1;
		}

		//保存数据副本
		memcpy(Mscb->lm_send_buf,send_data->data,send_data->len);
		Mscb->lm_send_tbytes = send_data->len;
		Mscb->lm_send_tfra = send_data->len/7+(((send_data->len%7)==0)?0:1);
		Mscb->lm_send_cnt = 0;
		Mscb->lm_resend_cnt = 0;

		//发送LM(0),开启 LMS_T2,LMS_T3,进入S0
		gbt27930_b_rlm_do_connect(rmcb);
		Mscb->lm_send_lms_t1_tick = 0;
		Mscb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
		Mscb->lm_send_lms_t3_tick = OpenChaoJi_os_get_ticks();
		Mscb->lm_send_state = LM_SEND_S0_ESTB_CONN;
		Mscb->rcved_ack_flag = RM_INVALID_VALUE;
	}

	return 0;
}

/*
* @brief: gbt27930 B类系统需要确认短消息的发送处理过程
* @param {OpenChaoJi_context_utility_transport} *context系统上下文指针，包含必要的环境信息。
* @return {*} 成功返回0，失败返回-1。
*/
int16_t OpenChaoJi_transport_gbt27930_b_rsm_send_process(struct OpenChaoJi_gbt27930_b_rmcb * rmcb)
{

	//可靠短消息发送处理
	if (rmcb->sm_send_state == RSM_S1_SEND_ING)
	{
		if (rmcb->sm_send_abort == 1)
		{
			LOG_ERR("transportsend abort, send fail");
			rmcb->sm_send_state = RSM_S2_SEND_END;
			rmcb->sm_send_result = OPENCHAOJI_UTILITY_TRANSPORT_MSG_SEND_FAILED;
			rmcb->sm_send_abort = 0;
			return 0;
		}
		if (rmcb->rcved_ack_flag == SM_ACK)
		{
			LOG_DEBUG("transportsend recv SM_ACK");
			rmcb->sm_send_state = RSM_S2_SEND_END;
			rmcb->sm_send_result = OPENCHAOJI_UTILITY_TRANSPORT_MSG_SEND_FINISHED;
			return 0;
		}

		//超时发送失败
		if ((OpenChaoJi_os_get_ticks() - rmcb->sm_send_first_tick) >= rmcb->sm_send_max_intvl_ms)
		{
			LOG_ERR("transportsend max_intvl_ms timeout, send fail");
			rmcb->sm_send_state = RSM_S2_SEND_END;
			rmcb->sm_send_result = OPENCHAOJI_UTILITY_TRANSPORT_MSG_SEND_FAILED;
			return 0;
		}

		//重新发送
		if ((OpenChaoJi_os_get_ticks() - rmcb->sm_send_last_tick) >= rmcb->sm_send_cycle_intvl_ms)
		{
			LOG_WARNING("now tick:%d - last tick:%d >= %d",OpenChaoJi_os_get_ticks(),rmcb->sm_send_last_tick,rmcb->sm_send_cycle_intvl_ms);
			LOG_WARNING("transportsend sm_send_cycle_intvl_ms timeout, send it again");
			gbt27930_b_rsm_sent_data(rmcb);
			rmcb->sm_send_last_tick = OpenChaoJi_os_get_ticks();
			return 0;
		}
	}
	else if (rmcb->sm_send_state == RSM_S2_SEND_END)
	{
		rmcb->sm_send_state = RSM_S0_IDLE;
	}

	return 0;
}

/*
* @brief: gbt27930 B类系统需要确认长消息的发送处理过程
* @param {OpenChaoJi_context_utility_transport} *context系统上下文指针，包含必要的环境信息。
* @return {*} 成功返回0，失败返回-1。
*/
int16_t OpenChaoJi_transport_gbt27930_b_rlm_send_process(struct can_pdu * pdu, struct OpenChaoJi_gbt27930_b_rmcb * rmcb)
{
	int16_t error = 0;

	switch (rmcb->lm_send_state)
	{
		case LM_SEND_IDLE:

			break;

		case LM_SEND_S0_ESTB_CONN:
			if (rmcb->rcved_ack_flag == LM_ACK)
			{
				//根据应答发送 LM(n), send_cnt 置 1. 开启LMS T1,关闭 LMS_T2, 进入S1
				rmcb->lm_ack_startframe_idx = pdu->data[1];
				rmcb->lm_ack_totalframe_nums = pdu->data[2];
				LOG_INFO("transportsend rmcb->lm_ack_startframe_idx = %d rmcb->lm_ack_totalframe_nums = %d",
							rmcb->lm_ack_startframe_idx, rmcb->lm_ack_totalframe_nums);

				error = gbt27930_b_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx);
				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
			}
			else if (rmcb->rcved_ack_flag == LM_NACK)
			{
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}

			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t2_tick) >= rmcb->lm_send_lms_t2_intvl_ms)
			{
				//如果接收方连  续3次响应超时，发送LM_NACK,进入S4
				rmcb->lm_resend_cnt++;
				LOG_ALERT("lm_resend_cnt =%d %d-%d>%d\n", rmcb->lm_resend_cnt, OpenChaoJi_os_get_ticks(), rmcb->lm_send_lms_t2_tick, rmcb->lm_send_lms_t2_intvl_ms);
				if (rmcb->lm_resend_cnt >= 3)
				{
					LOG_INFO("transportsend resend cnt > 3 close connect");
					gbt27930_b_rlm_sent_nack(rmcb);
					rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				}
				else
				{
					//否则发送LM(0), 重置LMS T2,保持S0
					gbt27930_b_rlm_do_connect(rmcb);
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_b_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
				LOG_INFO("transportsend T3 timeout, close connect");
			}

			break;

		case LM_SEND_S1_DATA_TRAN:	//data transmission

			if (rmcb->rcved_ack_flag == LM_ACK)
			{
				//保存k,根据应答发送LM(n), send_cnt置1,开启LMS_T1,关LMS_T2,保持S1
				rmcb->lm_ack_startframe_idx = pdu->data[1];
				rmcb->lm_ack_totalframe_nums = pdu->data[2];
				LOG_INFO("transportsend rmcb->lm_ack_startframe_idx = %d rmcb->lm_ack_totalframe_nums = %d",
							rmcb->lm_ack_startframe_idx, rmcb->lm_ack_totalframe_nums);

				error = gbt27930_b_rlm_sent_data(rmcb, rmcb->lm_ack_startframe_idx);
				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
			}
			else if (rmcb->rcved_ack_flag == LM_NACK)
			{
				LOG_DEBUG("transportrecv traning ev close connect");
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}

			//信息帧发送时间间隔LMS_T1定时器到
			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t1_tick) >= rmcb->lm_send_lms_t1_intvl_ms)
			{
				//期望发送为长消息最后一帧
				if ((rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt) == rmcb->lm_send_tfra)
				{
					LOG_DEBUG("transportrecv long frame is the last one");
					//发送LM(lm_tfra),send_cnt加1，关闭LMS_T1,开启LMS_T2,进入S3等待结束确认状态
					error = gbt27930_b_rlm_sent_data(rmcb, rmcb->lm_send_tfra);
					rmcb->lm_send_cnt++;
					rmcb->lm_send_lms_t1_tick = 0;
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_state = LM_SEND_S3_AWAIT_FIN_ACK;
					rmcb->lm_resend_cnt = 0;
				}
				//期望发送帧非接收方请求的  最后一帧，且非长消息最后一帧
				else if ((rmcb->lm_send_cnt < (rmcb->lm_ack_totalframe_nums - 1))
						&& ((rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt) < rmcb->lm_ack_totalframe_nums))
				{
					//发 送 L M ( n + send_cnt),send cnt加1,重置 LMS_ T1,保持Sl
					error = gbt27930_b_rlm_sent_data(rmcb, rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt);
					rmcb->lm_send_cnt++;
					rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
				}

				//期望发送帧为接收方请求的最后一帧且非长消息最后一帧，send_cnt = k- 1且n+send_cnt<lm tfra
				else if ((rmcb->lm_send_cnt == (rmcb->lm_ack_totalframe_nums - 1))
						&& ((rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt) < rmcb->lm_ack_totalframe_nums))
				{
					LOG_DEBUG("transportrecv long package is the last one");
					//发 送 L M ( n + send_cnt),send cnt加1 . 关闭 LMS T1,开启LMS_ T2,进入S2
					error = gbt27930_b_rlm_sent_data(rmcb, rmcb->lm_ack_startframe_idx + rmcb->lm_send_cnt);
					rmcb->lm_send_cnt++;
					rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
					rmcb->lm_send_state = LM_SEND_S2_AWAIT_RESP_ACK;
					rmcb->lm_resend_cnt = 0;
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				LOG_DEBUG("transportrecv T3 timeout close connect");
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_b_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
			}

			break;

		case LM_SEND_S2_AWAIT_RESP_ACK:

			if (rmcb->rcved_ack_flag == LM_ACK)
			{
				//根据应答调整LM的帧序号为n, send_cnt 置 1, 开启LMS_T1,关闭LMS_T2, 进入S1
				rmcb->lm_ack_startframe_idx = pdu->data[1];
				rmcb->lm_ack_totalframe_nums = pdu->data[2];

				error = gbt27930_b_rlm_sent_data(rmcb, rmcb->lm_ack_startframe_idx);
				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;

			}
			else if (rmcb->rcved_ack_flag == LM_NACK)
			{
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}
			//如果接收方连  续3次超时，发送LM_NACK,进入S4,否则发送LM(n+k?1),开启LMST2,进入S2
			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t2_tick) >= rmcb->lm_send_lms_t2_intvl_ms)
			{
				//如果接收方连  续3次响应超时，发送LM_NACK,进入S4
				rmcb->lm_resend_cnt++;
				if (rmcb->lm_resend_cnt >= 3)
				{
					LOG_DEBUG("transportrecv LM_SEND_S2_AWAIT_RESP_ACK timeout");
					gbt27930_b_rlm_sent_nack(rmcb);
					rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				}
				else
				{
					//否则发送LM(0), 重置LMS T2,保持S0
					error = gbt27930_b_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx + rmcb->lm_ack_totalframe_nums -1);
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_b_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
			}

			break;

		case LM_SEND_S3_AWAIT_FIN_ACK:

			if (rmcb->rcved_ack_flag == LM_ACK)
			{
				//根据应答调整LM的帧序号为n, send_cnt 置 1, 开启LMS_T1,关闭LMS_T2, 进入S1
				rmcb->lm_ack_startframe_idx = pdu->data[1];
				rmcb->lm_ack_totalframe_nums = pdu->data[2];
				error = gbt27930_b_rlm_sent_data(rmcb,rmcb->lm_ack_startframe_idx);

				rmcb->lm_send_cnt = 1;
				rmcb->lm_send_lms_t1_tick = OpenChaoJi_os_get_ticks();

				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_state = LM_SEND_S1_DATA_TRAN;
			}
			else if (rmcb->rcved_ack_flag == LM_NACK)
			{
				//LM_NACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}
			else if (rmcb->rcved_ack_flag == LM_EndACK)
			{
				//LM_EndofACK,进入S4
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
			}

			//如果接收方连续3次响应超时，发送LMN_ACK,进入S4,否则发送LM(lm_tfra),开启LMS_T2,保持S3
			else if ((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t2_tick) >= rmcb->lm_send_lms_t2_intvl_ms)
			{
				//如果接收方连  续3次响应超时，发送LM_NACK,进入S4
				rmcb->lm_resend_cnt++;
				if (rmcb->lm_resend_cnt >= 3)
				{
					LOG_DEBUG("transportrecv LM_SEND_S3_AWAIT_FIN_ACK timeout");
					gbt27930_b_rlm_sent_nack(rmcb);
					rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				}
				else
				{
					//否则发送LM(0), 重置LMS T2,保持S3
					error = gbt27930_b_rlm_sent_data(rmcb,rmcb->lm_send_tfra);
					rmcb->lm_send_lms_t2_tick = OpenChaoJi_os_get_ticks();
				}
			}
			else if (((OpenChaoJi_os_get_ticks() - rmcb->lm_send_lms_t3_tick) >= rmcb->lm_send_lms_t3_intvl_ms)
					|| (rmcb->lm_send_active_abort == 1))
			{
				//LMS_T3定时器到或主动中止,发送LM_NACK,进入S4
				gbt27930_b_rlm_sent_nack(rmcb);
				rmcb->lm_send_state = LM_SEND_S4_CLOSE_CONN;
				rmcb->lm_send_active_abort = 0;
			}
			break;

		case LM_SEND_S4_CLOSE_CONN:
				rmcb->lm_send_lms_t1_tick = 0;
				rmcb->lm_send_lms_t2_tick = 0;
				rmcb->lm_send_lms_t3_tick = 0;
				rmcb->lm_send_cnt = 0;
				rmcb->lm_resend_cnt = 0;
				// OpenChaoJi_os_free(rmcb->lm_send_buf);
				OPEN_CHAOJI_MEM_FREE_CHECK(rmcb->lm_send_buf);
				rmcb->lm_send_state = LM_SEND_IDLE;
			break;

		default: break;
	}

	if (error < 0)
	{
		LOG_CRIT("system b rlm send error");
	}

	return 0;
}
/*
* @brief: 需要确认短消息信息发送
* @param {OpenChaoJi_context_utility_transport} *context 系统上下文指针，包含必要的环境信息。
* @return {*}成功返回0，失败返回-1。
*/
int16_t gbt27930_b_rsm_sent_data(struct OpenChaoJi_gbt27930_b_rmcb * rmcb)
{
	struct can_pdu pdu;
	uint8_t i;
    int16_t ret;

	pdu.can_id.bit.sa = rmcb->src_addr;
	pdu.can_id.bit.ps = rmcb->dest_addr;
	pdu.can_id.bit.pf = PF_RSMIF;
	pdu.can_id.bit.dp = 0;
	pdu.can_id.bit.edp = 0;
	pdu.can_id.bit.p = 0x04;
	pdu.can_id.bit.rsvd = 0;

	pdu.can_dlc = 8;

	//不足8字节的填充OxFF
	for (i = 0;i < 8;i++)
	{
		if (i < rmcb->sm_send_data_len){
			pdu.data[i] = rmcb->sm_send_buf[i];
		}
		else{
			pdu.data[i] = 0xff;
		}
	}

	ret = (*rmcb->can_output_func)(rmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->b_rsm[%08X][%d]", rmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}

/*
* @brief: 长消息发送连接
* @param {OpenChaoJi_context_utility_transport} *context 系统上下文指针，包含必要的环境信息。
* @return {*}成功返回0，失败返回-1。
*/
int16_t gbt27930_b_rlm_do_connect(struct OpenChaoJi_gbt27930_b_rmcb * rmcb)
{
	struct can_pdu pdu;
    int16_t ret;

	pdu.can_id.bit.sa = rmcb->src_addr;
	pdu.can_id.bit.ps = rmcb->dest_addr;

	pdu.can_id.bit.pf = PF_LMIF;
	pdu.can_id.bit.dp = 0;
	pdu.can_id.bit.edp = 0;
	pdu.can_id.bit.p = 6;
	pdu.can_id.bit.rsvd = 0;
	pdu.can_dlc = 8;

	pdu.data[0] = 0;
	pdu.data[1] = rmcb->lm_send_tfra;	//发送总帧数
	pdu.data[2] = rmcb->lm_send_tbytes & 0x00ff;	//总字节数
	pdu.data[3] = rmcb->lm_send_tbytes>>8;
	pdu.data[4] = 0xff;
	pdu.data[5] = 0xff;
	pdu.data[6] = 0xff;
	pdu.data[7] = 0xff;

	ret = (*rmcb->can_output_func)(rmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->b_rlm_conn[%08X][%d]", rmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}

/*
* @brief: 长消息发送信息帧数据
* @param {OpenChaoJi_context_utility_transport} *context 系统上下文指针，包含必要的环境信息。
* @param {uint8_t} frame_idx 发送信息帧的编号
* @return {*}成功返回0，失败返回-1。
*/
int16_t gbt27930_b_rlm_sent_data(const struct OpenChaoJi_gbt27930_b_rmcb * rmcb, uint8_t frame_idx)
{
	struct can_pdu pdu;
	uint8_t i;
    int16_t ret;
	uint16_t offset = (frame_idx-1)*7;

	pdu.can_id.bit.sa = rmcb->src_addr;
	pdu.can_id.bit.ps = rmcb->dest_addr;
	pdu.can_id.bit.pf = PF_LMIF;
	pdu.can_id.bit.dp = 0;
	pdu.can_id.bit.edp = 0;
	pdu.can_id.bit.p = 0x06;
	pdu.can_id.bit.rsvd = 0;

	pdu.can_dlc = 8;

	pdu.data[0] = frame_idx;
	//不足7字节的填充OxFF
	for (i = 0;i < 7;i++)
	{
		if ((offset+i) < rmcb->lm_send_tbytes){
			pdu.data[i+1] = rmcb->lm_send_buf[offset+i];
		}
		else{
			pdu.data[i+1] = 0xff;
		}
	}

	ret = (*rmcb->can_output_func)(rmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->b_rlm_data[%08X][%d]", rmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}

/*
* @brief: 长消息发送nack函数
* @param {OpenChaoJi_context_utility_transport} *context 系统上下文指针，包含必要的环境信息。
* @return {*}成功返回0，失败返回-1。
*/
int16_t gbt27930_b_rlm_sent_nack(const struct OpenChaoJi_gbt27930_b_rmcb * rmcb)
{
	struct can_pdu pdu;
    int16_t ret;

	pdu.can_id.bit.sa = rmcb->src_addr;
	pdu.can_id.bit.ps = rmcb->dest_addr;
	pdu.can_id.bit.pf = PF_RMCF;
	pdu.can_id.bit.dp = 0;
	pdu.can_id.bit.edp = 0;
	pdu.can_id.bit.p = 3;
	pdu.can_id.bit.rsvd = 0;
	pdu.can_dlc = 8;

	pdu.data[0] = 2;
	pdu.data[1] = 0xff;
	pdu.data[2] = 0xff;
	pdu.data[3] = 0xff;
	pdu.data[4] = 0xff;
	pdu.data[5] = 0xff;
	pdu.data[6] = 0xff;
	pdu.data[7] = 0xff;

	ret = (*rmcb->can_output_func)(rmcb->param, &pdu);

	if (s_transport_debug_enable)
	{
		LOG_DATA_TRANSPORT("[%d]->b_rlm_nack[%08X][%d]", rmcb->tag, pdu.can_id.uint32_tWord, pdu.can_dlc);
		LOG_DATA_BUFF_TRANSPORT(pdu.data, pdu.can_dlc);
	}

	return ret;
}


#endif
